package com.suredy.app.porject.tools;

import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 断点续传工具（下载工具）
 * 
 * @author VIVID.G
 * @since 2016-3-18
 * @version v0.1
 */
public class MultiplePointDownload {

	private final static Logger log = LoggerFactory.getLogger(MultiplePointDownload.class);

	/* 缓存大小，默认4K */
	private final int BUFFER_SIZE = 1024 * 4;

	/* Range正则 */
	private String HEADER_RANGE = "bytes=(\\d*)-(\\d*)";

	public void download(HttpServletRequest req, HttpServletResponse resp, File file) throws IOException {
		if (req == null)
			throw new IllegalArgumentException("Confirm! Is it a HttpServletRequest ?");
		if (resp == null)
			throw new IllegalArgumentException("Confirm! Is it a HttpServletResponse ?");
		if (file == null || !file.isFile())
			throw new IllegalArgumentException("Confirm! File exists ?");

		// 通知客户端支持断点
		resp.setHeader("Accept-Ranges", "bytes");

		RandomAccessFile raf = new RandomAccessFile(file, "r");
		long len = raf.length();
		long[] area = {0, len};

		// 重置下载区块
		this.resetRange(req, resp, area);

		resp.setHeader("Content-Length", "" + (area[1] - area[0]));
		resp.setHeader("Content-Range", "bytes " + area[0] + "-" + area[1] + "/" + len);

		raf.seek(area[1]);
		// TODO: 下载制定内容，下面的代码是下载剩下的所有内容
		// TODO: 需要考虑multi range、if-range的情况
		// TODO: see http://www.cnblogs.com/Googler/archive/2010/08/19/1803700.html
		// TODO: see http://blog.csdn.net/shuimuniao/article/details/8086438
		byte[] b = new byte[2048];
		int i;
		OutputStream outs = resp.getOutputStream();
		while ((i = raf.read(b)) != -1) {
			outs.write(b, 0, i);
		}
		raf.close();
	}

	private long[] resetRange(HttpServletRequest req, HttpServletResponse resp, long[] area) {
		if (req == null)
			return area;

		if (area == null || area.length != 2 || area[1] <= area[0])
			throw new IllegalArgumentException("Invalid param area(long[]).");

		String range = req.getHeader("Range");

		// 非Range请求
		if (StringUtils.isBlank(range))
			return area;

		range = range.trim();

		Pattern p = Pattern.compile(this.HEADER_RANGE);
		Matcher m = p.matcher(range);

		// 不符合Range请求
		if (!m.matches())
			return area;

		String sPos = m.group(1);
		String sOff = m.group(2);

		long pos = StringUtils.isBlank(sPos) ? 0 : Long.parseLong(sPos);
		long off = StringUtils.isBlank(sOff) ? 0 : Long.parseLong(sOff);

		if (off <= pos)
			return area;

		area[0] = pos;
		area[1] = off;

		// 返回206状态
		resp.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);

		return area;
	}

	public static void main(String[] args) {
		String[] ss = "1-2".split("\\-");

		System.out.println(ss.length);

		for (String s : ss) {
			System.out.println(s);
		}
	}

}
